﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Xml;
using System.Security.Cryptography;

namespace CheckSumCreator
{
    class CheckSumCreator
    {

        private string pathToFolder;

        private string pathToXML;

        private string[] files;

        private DirectoryInfo FolderInfo;

        public CheckSumCreator(string pathToFolder, string pathToXml)
        {
            this.pathToFolder = pathToFolder;
            this.pathToXML = pathToXml;
            this.FolderInfo = new DirectoryInfo(pathToFolder);
        }

        public bool BuildXml()
        {
            files = Directory.GetFiles(this.pathToFolder, "*.*", SearchOption.AllDirectories);

            if (File.Exists(this.pathToXML)) return false;

            using (var tr = new XmlTextWriter(this.pathToXML, Encoding.UTF8))
            {
                tr.WriteStartDocument();
                tr.WriteStartElement("head");
                tr.WriteEndElement();
            }

            var doc = new XmlDocument();
            doc.Load(this.pathToXML);

            foreach (string f in files)
            {
                var fi = new FileInfo(f);
                XmlNode row = doc.CreateElement("File");
                if (doc.DocumentElement != null) doc.DocumentElement.AppendChild(row);
                XmlAttribute id = doc.CreateAttribute("name");
                id.Value = fi.Name;
                if (row.Attributes != null) row.Attributes.Append(id);
                XmlAttribute pathRow = doc.CreateAttribute("path");
                pathRow.Value = fi.FullName.Substring(this.FolderInfo.FullName.IndexOf(this.FolderInfo.Name, System.StringComparison.Ordinal) + this.FolderInfo.Name.Count() + 1);
                if (row.Attributes != null) row.Attributes.Append(pathRow);
                XmlAttribute hashRow = doc.CreateAttribute("hash");
                hashRow.Value = GetMd5HashFromFile(f);
                if (row.Attributes != null) row.Attributes.Append(hashRow);
            }
            doc.Save(this.pathToXML);
            return true;
        }

        /// <summary>
        /// Возвращает хеш сумму файла
        /// </summary>
        /// <param name="fileName">Путь к файлу</param>
        /// <returns>Возвращает хеш сумму</returns>
        private string GetMd5HashFromFile(string fileName)
        {
            using (var file = new FileStream(fileName, FileMode.Open, FileAccess.Read))
            {
                byte[] retVal = CalculateHash(file);
                return GetStringHash(retVal);
            }
        }

        private string GetStringHash(byte[] retVal)
        {
            var stringBuilder = new StringBuilder();

            for (int i = 0; i < retVal.Length; i++)
            {
                stringBuilder.Append(retVal[i].ToString("x2"));
            }

            return stringBuilder.ToString();
        }

        private byte[] CalculateHash(Stream file)
        {
            using (MD5 md5 = new MD5CryptoServiceProvider())
            {
                return md5.ComputeHash(file);
            }
        }

        public void Destroy()
        {
            try
            {
                File.Delete(this.pathToXML);
            }
            catch (Exception e)
            {
                Console.Error.Write(e.Message);
            }

        }

    }
}
